# import time
# import xml.etree.ElementTree as ET
#
# import gevent
# from gevent import monkey
# monkey.patch_all()
#
# import jenkins
# from collections import defaultdict
# from javcra.common import constant
# from requests.exceptions import RequestException
# from javcra.libs.log import logger
#
#
# class JenkinsJob(object):
#
#     def __init__(self, base_url, jenkins_user, jenkins_passwd, paral_num, packages, branch, update_time):
#         self.server = jenkins.Jenkins(base_url, username=jenkins_user, password=jenkins_passwd)
#         self.paral_job_num = paral_num
#         self.packages = packages
#         self.date = None
#         self.branch = branch
#         self.update_time = update_time
#
#     def get_job_config(self, job_name):
#         """
#         get template job config
#         Args:
#             job_name:
#
#         Returns:
#
#         """
#         return self.server.get_job_config(job_name)
#
#     def build_jenkins_job(self, job_name, params):
#         """
#         build the trigger job
#         Args:
#             job_name:
#
#         Returns:
#
#         """
#         try:
#             self.server.enable_job(job_name)
#             self.server.build_job(job_name, params)
#             # print("build 信息", self.server.get_job_info(job_name))
#             last_build = self.server.get_job_info(job_name)["lastCompletedBuild"]
#             if last_build:
#                 last_build_number = last_build["number"]
#                 build_info = self.server.get_build_info(job_name, last_build_number)
#
#                 if build_info["result"] == "SUCCESS":
#                     print("[INFO]  build successfully.")
#                     logger.info("{} build successfully".format(job_name))
#                 else:
#                     print("[ERROR] build failed.")
#                     logger.error("{} build failed".format(job_name))
#         except RequestException:
#             print("[ERROR] Bad Request for url, please check the job name and parameters for trigger building.")
#
#     def create_new_job(self, job_name, job_config):
#         """
#         job_name: path:str
#         job_config: xml:str
#         """
#         try:
#             self.server.create_job(job_name, job_config)
#             return True
#         except jenkins.JenkinsException as e:
#             print("[ERROR] failed to create %s. %s", (job_name, e))
#             logger.error("failed to create %s. %s", (job_name, e))
#             return False
#
#     def generate_parallel_job_name(self):
#         """
#         生成并行任务的job name
#         Returns:
#
#         """
#         parallel_job_dict = {"aarch64": [], "x86": []}
#         base_path = self.get_base_path()
#         for index in range(1, self.paral_job_num + 1):
#             parallel_job_dict["aarch64"].append(base_path + "/aarch64/" + str(index))
#             parallel_job_dict["x86"].append(base_path + "/x86_64/" + str(index))
#         return parallel_job_dict
#
#     @staticmethod
#     def get_job_pkg_dict(packages, release_jobs):
#         """
#         """
#         job_num = len(release_jobs)
#         job_pkg_dict = defaultdict(list)
#
#         for idx, pkg in enumerate(packages):
#             job_name = release_jobs[idx % job_num]
#             job_pkg_dict[job_name].append(pkg)
#         return job_pkg_dict
#
#     def update_config(self, target_job, template_job_config):
#
#         # 获取trigger需要触发的并行任务
#         paral_job_dict = self.generate_parallel_job_name()
#         trigger_jobs = []
#         trigger_jobs.extend(paral_job_dict["aarch64"])
#         trigger_jobs.extend(paral_job_dict["x86"])
#
#         # 获取每个任务对应的软件包
#         packages_dct = dict()
#         if "aarch64" in target_job:
#             packages_dct = self.get_job_pkg_dict(self.packages, paral_job_dict["aarch64"])
#         elif "x86" in target_job:
#             packages_dct = self.get_job_pkg_dict(self.packages, paral_job_dict["x86"])
#
#         root = ET.fromstring(template_job_config.encode("utf-8"))
#
#         # 修改trigger
#         ele_projects = root.find("publishers/hudson.plugins.parameterizedtrigger.BuildTrigger//projects")
#         if ele_projects is not None:
#             ele_projects.text = ",".join(trigger_jobs)
#
#         if "trigger" not in target_job:
#             # 修改任务模板
#             # ele_cmd = root.find("builders/hudson.tasks.Shell//command")
#             # if ele_cmd is not None and packages_dct.get(target_job):
#             #     verify_pkgs = ",".join(packages_dct.get(target_job))
#             #     ele_cmd.text = ele_cmd.text.strip() + " " + verify_pkgs
#
#             ele_cmd = root.find("properties/hudson.model.ParametersDefinitionProperty//parameterDefinitions")
#             if ele_cmd is not None and packages_dct.get(target_job):
#                 for node in ele_cmd:
#                     verify_pkgs = ",".join(packages_dct.get(target_job))
#                     key = node.find('name').text
#                     if key == "PKG_NAME":
#                         node.find('defaultValue').text = verify_pkgs
#
#                     if key == "UPDATE_TIME":
#                         node.find('defaultValue').text = self.update_time
#
#                     if key == "BRANCH":
#                         node.find('defaultValue').text = self.branch
#
#         # 修改comment
#         ele_comment = root.find("publishers/join.JoinTrigger//projects")
#         if ele_comment is not None:
#             ele_comment.text = "".join(self.get_jobs_to_create(constant.COMMENT_TM_JOB))
#         return ET.tostring(root).decode('utf-8')
#
#     def get_base_path(self):
#         """
#
#
#         Returns:
#
#         """
#         path_prefix = constant.JENKINS_PATH_PREFIX
#         base_path = path_prefix + "/openeuler_" + self.date
#         return base_path
#
#     def create_folder(self):
#         base_path = self.get_base_path()
#         try:
#             self.server.create_folder(base_path)
#             self.server.create_folder(base_path + "/aarch64")
#             self.server.create_folder(base_path + "/x86_64")
#         except jenkins.JenkinsException as e:
#             print(e)
#
#     def get_jobs_to_create(self, template_job):
#         # 根据输入的模板获取需要新建的jobs,返回值为list类型
#         base_path = self.get_base_path()
#         paral_job_dict = self.generate_parallel_job_name()
#
#         if "trigger" in template_job:
#             return [base_path + "/trigger"]
#         elif "comment" in template_job:
#             return [base_path + "/comment"]
#         elif "aarch64" in template_job:
#             return paral_job_dict["aarch64"]
#         else:
#             return paral_job_dict["x86"]
#
#     def create_build_jenkins_job_for_update(self):
#         """
#         分别创建trigger、aarch64、x86、comment任务
#         Returns:
#
#         """
#         self.date = time.strftime("%Y%m%d%H%M%S", time.localtime())
#         self.create_folder()
#
#         # 创建trigger
#         template_trigger = constant.TRIGGER_TM_JOB
#         if template_trigger:
#             target_jobs = self.get_jobs_to_create(template_trigger)
#             self.create_multi_job(template_trigger, target_jobs)
#         else:
#             print("[ERROR] error occurred when getting template trigger job name.")
#             logger.error("[ERROR] error occurred when getting template trigger job name.")
#
#
#         # 创建aarch64并行任务
#         template_aarch64 = constant.AARCH64_TM_JOB
#         if template_aarch64:
#             target_jobs = self.get_jobs_to_create(template_aarch64)
#             self.create_multi_job(template_aarch64, target_jobs)
#         else:
#             print("[ERROR] error occurred when getting template aarch64 job name.")
#
#         # 创建x86并行任务
#         template_x86 = constant.X86_TM_JOB
#         if template_x86:
#             target_jobs = self.get_jobs_to_create(template_x86)
#             self.create_multi_job(template_x86, target_jobs)
#         else:
#             print("[ERROR] error occurred when getting template x86 job name.")
#
#         # 创建comment任务
#         template_comment = constant.COMMENT_TM_JOB
#         if template_comment:
#             target_jobs = self.get_jobs_to_create(template_comment)
#             self.create_multi_job(template_comment, target_jobs)
#         else:
#             print("[ERROR] error occurred when getting template comment job name.")
#
#         # build trigger jobs
#         target_trigger_job = "".join(self.get_jobs_to_create(template_trigger))
#         parameters = {"ScanOSSAPIURL": constant.JENKINS_API_URL,
#                       "ScanOSSResultRepo": constant.JENKINS_SERVER_REPO}
#         self.build_jenkins_job(target_trigger_job, parameters)
#
#     def create_multi_job(self, template_job, jobs, concurrency=75, retry=3):
#         """
#         启动
#         :param jobs: 任务列表
#         :param concurrency: 并发量
#         :param retry: 尝试次数
#         :param interval: 每次batch请求后sleep时间（秒），
#         :return:
#         """
#
#         def create_multi_job_once(target_jobs):
#             """
#             create new job once for retry
#             """
#             batch = int((len(target_jobs) + concurrency - 1) / concurrency)
#             _failed_jobs = []
#             for index in range(batch):
#                 works = [gevent.spawn(self.dispatch, job, template_job)
#                          for job in target_jobs[index * concurrency: (index + 1) * concurrency]]
#                 logger.info("{} works, {}/{} ".format(len(works), index + 1, batch))
#                 print("[INFO] {} works, {}/{} ".format(len(works), index + 1, batch))
#                 gevent.joinall(works)
#                 for work in works:
#                     if work.value["result"]:
#                         logger.info("job {} ... ok".format(work.value["job"]))
#                         print("[INFO] create job {} ... ok".format(work.value["job"]))
#                     else:
#                         _failed_jobs.append(work.value["job"])
#                         logger.error("job {}  ... failed".format(work.value["job"]))
#                         print("[ERROR] create job {} ... failed".format(work.value["job"]))
#             return _failed_jobs
#
#         failed_jobs = create_multi_job_once(jobs)
#
#         for index in range(retry):
#             if not failed_jobs:
#                 break
#             logger.info("{} jobs failed, retrying {}/{}".format(len(failed_jobs), index + 1, retry))
#             print("[INFO] {} jobs failed, retrying {}/{}".format(len(failed_jobs), index + 1, retry))
#             failed_jobs = create_multi_job_once(failed_jobs)
#
#         if failed_jobs:
#             print("[ERROR] {} failed jobs".format(len(failed_jobs)))
#             logger.warning("{} failed jobs".format(len(failed_jobs)))
#             logger.warning("{}{}".format(",".join(failed_jobs[:100]), "..." if len(failed_jobs) > 100 else ""))
#
#     def dispatch(self, job, template_job):
#         """
#         分发任务
#         :param template_job: template job
#         :param job: 目标任务
#         :return:
#         """
#         temp_job_config = self.get_job_config(template_job)
#         updated_config = self.update_config(job, temp_job_config)
#         create_result = self.create_new_job(job, updated_config)
#         return {"job": job, "result": create_result}
#
#
# if __name__ == '__main__':
#     # 创建实例
#     paral_num = 5
#     packages = ["bluez", "edk2", "httpd", "jetty", "libvma"]
#
#     branch = "openEuler-20.03-LTS-SP1"
#     update_time = "20210630"
#     server = JenkinsJob('https://jenkins.openeuler.org', 'tuShenmei', '062725tu_TU', paral_num, packages,
#                         branch, update_time)
#
#     server.create_build_jenkins_job_for_update()
